package com.tj.collection.service.third;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fqgj.common.utils.MD5;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.exception.common.ApplicationException;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.tj.collection.utils.ConfigUtil;
import com.tj.collection.utils.HttpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * User: pavan
 * Date: 2020/2/20
 * Time: 下午6:37
 */
@Service
public class OutboundService {

    private static final Log LOGGER = LogFactory.getLog(OutboundService.class);

    @Autowired
    private ConfigUtil configUtil;

    /**
     * 0.测试地址:tel.jishuyuansu.com
     * 1.测试环境的clientId和clientSecret
     * ---clientId :38UvGsdEme  clientSecret:0fa980e311e471944a6b82380c6fcf46
     * 2.线路id和话术模板id
     * ---线路id:20
     * ---话术模板id:20200211649988512323416589_en
     */
    //测试
//    private static String API_URL = "https://ip:port/api/v1/thirdApi";
//    private static String clientId = "38UvGsdEme";
//    private static String clientSecret = "0fa980e311e471944a6b82380c6fcf46";

    /**
     * 线上用
     * 线路：lineIds:425，话术：Key: 20200219106697945194455285_en
     */

    //线上
//    private static String API_URL = "https://tel.jishuyuansu.com/api/v1/thirdApi"; //https://vdc.jishuyuansu.com/api/v1/thirdApi
//    private static String clientId = "b5p5t41FZW";
//    private static String clientSecret = "df4adfe4394fcae97739870f2b408ef4";

    private static TreeMap<String, Object> publicRequest = new TreeMap<>();

    private static Map<String, String> headers = new HashMap<>();

    static {
        publicRequest.put("clientId", "");//分配的用户 clientId
        publicRequest.put("sign", "");//签名字符串:MD5
        publicRequest.put("signType", "MD5");
        publicRequest.put("nonce", "");//6位随机字符串(字母数字组合，10分钟不允许重复)
        publicRequest.put("timestamp", System.currentTimeMillis() + "");//时间戳

        headers.put("Content-Type", "application/json");
    }

    private static String getNonce() {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        return uuid.substring(uuid.length() - 6);
    }

    public static void main(String[] args) {

        JSONObject defaultConfig = new JSONObject();
        defaultConfig.put("apiUrl", "https://vdc.jishuyuansu.com/api/v1/thirdApi");
        defaultConfig.put("clientId", "b5p5t41FZW");
        defaultConfig.put("clientSecret", "df4adfe4394fcae97739870f2b408ef4");
        defaultConfig.put("botenceId", "20200219106697945194455285_en");
        defaultConfig.put("lineIds", "425,431");//425、431 是我们自己的线路

        OutboundConfig outboundConfig = JSON.parseObject(defaultConfig.toJSONString(), OutboundConfig.class);

        String s = new  OutboundService().getCallLine();
        System.out.println(s);
//        new OutboundService().queryPlanParams("20200219106697945194455285_en");
//
//        String lineList = new OutboundService().getCallLine();
//        String[] lineArr = lineList.split("\\|");
//        StringBuffer sb = new StringBuffer();
//        for (String s : lineArr) {
//            sb.append(s.split("\\^")[0]).append(",");
//        }

//        new OutboundService().getBatchPlanList("cm1584511476385");
//
//        new OutboundService().getBatchPlanCallList("cm1584511476385",1,1000);

//        new OutboundService().addPlan(
//                "cm" + System.currentTimeMillis(),
//                DateUtil.getDate(new Date(), "yyyyMMdd"),
//                "9100453818^dueday-money^2020/03/22-3040",
//                "",
//                ""
//        );
    }

    /**
     * 对请求参数进行签名，返回请求body
     *
     * @param request
     * @return
     */
    private String addPublicRequestAndSign(TreeMap<String, Object> request) {
        OutboundConfig outboundConfig = this.getOutboundConfig();
        request.putAll(publicRequest);
        request.put("clientId", outboundConfig.getClientId());
        request.put("nonce", getNonce());
        request.put("timestamp", System.currentTimeMillis() + "");
        StringBuffer signSource = new StringBuffer();
        for (Map.Entry<String, Object> entry : request.entrySet()) {
            if ("sign".equals(entry.getKey()) || "signType".equals(entry.getKey())) {
                continue;
            }
            signSource.append(entry.getKey() + "=" + entry.getValue() + "&");
        }
        String str = signSource.toString().substring(0, signSource.length() - 1) + outboundConfig.getClientSecret();
        String sign = MD5.md5(str);
        request.put("sign", sign);
        LOGGER.info("签名生成,str:{},sign:{}", str, sign);
        return JSON.toJSONString(request);
    }

    private OutboundConfig getOutboundConfig() {
        JSONObject jsonObject = configUtil.getOutboundParams();
        OutboundConfig config = JSON.parseObject(jsonObject.toJSONString(), OutboundConfig.class);
        return config;
    }

    /**
     * 获取用户线路列表
     *
     * @return
     */
    public String getCallLine() {
        String url = this.getOutboundConfig().getApiUrl() + "/getCallLine";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,getCallLine请求及应答,request:{},response:{}", request, response);
        String body = null;
        StringBuffer sb = new StringBuffer();
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                JSONObject bodyObj = JSON.parseObject(body);
                String lineList = bodyObj.getString("lineList");
                if (StringUtils.isEmpty(lineList)) {
                    return null;
                }
                String[] sArr1 = lineList.split("\\|");
                for (String s : sArr1) {
                    String line = s;
                    if (s.contains("^")) {
                        String[] sArr2 = s.split("\\^");
                        line = sArr2[0];
                    }
                    sb.append(line).append(",");
                }
                return sb.substring(0, sb.length() - 1);
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,getCallLine处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,getCallLine处理失败");
        }
        return null;
    }

    /**
     * 获取用户话术
     */
    public String getBotence() {
        String url = this.getOutboundConfig().getApiUrl() + "/getBotence";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,getBotence请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                System.out.println(body);
                return body;
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,getBotence处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,getBotence处理失败");
        }
        return null;
    }

    /**
     * 获取坐席组信息
     */
    public void getGroups() {
        String url = this.getOutboundConfig().getApiUrl() + "/getGroups";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,getGroups请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                System.out.println(body);
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,getGroups处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,getBotence处理失败");
        }

        //TODO 业务处理
    }

    /**
     * 获取用户话术
     */
    public void queryPlanParams(String botenceId) {
        String url = this.getOutboundConfig().getApiUrl() + "/queryPlanParams";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        requestMap.put("botenceId", botenceId);
        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,queryPlanParams请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                System.out.println(body);
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,queryPlanParams处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,queryPlanParams处理失败");
        }

        //TODO 业务处理
    }

    /**
     * 添加拨打任务
     *
     * @param batchName
     * @param callDate   例：api1_11564_en
     * @param mobileList 例：18335618326^afg^123|18335618326^afg^123
     * @param botenceId
     * @param lineIds    线路id 例：20,87
     */
    public String addPlan(String batchName, String callDate, String mobileList, String botenceId, String lineIds) {
        String url = this.getOutboundConfig().getApiUrl() + "/addPlan";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        requestMap.put("batchName", batchName);//批次名称，用户下唯一
        requestMap.put("mobileList", mobileList);//客户列表,格式为:手机号码^附加数据^参数
        requestMap.put("callDate", callDate);//外呼电话拨打日期 yyyyMMdd
        requestMap.put("botenceId", StringUtils.isNotEmpty(botenceId) ? botenceId : this.getOutboundConfig().getBotenceId());//话术模板 id
        requestMap.put("lineIds", StringUtils.isNotEmpty(lineIds) ? lineIds : this.getCallLine());//一个计划单条线路
        requestMap.put("clear", "1");//是否当日夜间清除未完成 计划，可传的值包括 0 和 1共2种。0表示不清除1表示清除
        requestMap.put("callHour", "9,10,11,12,13,14,15,16,17,18,19");//外呼电话拨打时间，可传的值以小时为单位，以英 文逗号(,)分隔 时间范围9-19
        requestMap.put("notifyBatchUrl", getBetterUrl(configUtil == null ? "http://fat-admin-api.cashmama.in/" : configUtil.getAdminUrl()) + "/collection/outbound/plan/batch/callback");//批次回调地址
        requestMap.put("notifyUrl", getBetterUrl(configUtil == null ? "http://fat-admin-api.cashmama.in/" : configUtil.getAdminUrl()) + "/collection/outbound/plan/detail/callback");//单笔回调地址

        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,addPlan请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                return body;
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,addPlan处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,addPlan处理失败");
        }
        return null;
    }


    /**
     * 无逾期AI电话
     *
     * @param batchName
     * @param callDate
     * @param mobileList
     * @param botenceId
     * @param lineIds
     * @return
     */
    public Boolean noOverdueCall(String batchName, String callDate, String mobileList, String botenceId, String lineIds, String batchUrl, String singleUrl) {
        LOGGER.info("无逾期AI电话 第三方调用开始");
        String url = this.getOutboundConfig().getApiUrl() + "/addPlan";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        requestMap.put("batchName", batchName);//批次名称，用户下唯一
        requestMap.put("mobileList", mobileList);//客户列表,格式为:手机号码^附加数据^参数
        requestMap.put("callDate", callDate);//外呼电话拨打日期 yyyyMMdd
        requestMap.put("botenceId", StringUtils.isNotEmpty(botenceId) ? botenceId : this.getOutboundConfig().getBotenceId());//话术模板 id
        requestMap.put("lineIds", StringUtils.isNotEmpty(lineIds) ? lineIds : this.getCallLine());//一个计划单条线路
        requestMap.put("clear", "0");//是否当日夜间清除未完成 计划，可传的值包括 0 和 1共2种。0表示不清除1表示清除
        requestMap.put("callHour", "9,10,11,12,13,14,15,16,17,18,19");//外呼电话拨打时间，可传的值以小时为单位，以英 文逗号(,)分隔 时间范围9-19
        requestMap.put("notifyBatchUrl", getBetterUrl(configUtil == null ? "http://fat-admin-api.cashmama.in/" : configUtil.getAdminUrl()) + batchUrl);//批次回调地址
        requestMap.put("notifyUrl", getBetterUrl(configUtil == null ? "http://fat-admin-api.cashmama.in/" : configUtil.getAdminUrl()) + singleUrl);//单笔回调地址

        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,addPlan请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                return resp.getBoolean("success");
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,addPlan处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,addPlan处理失败");
        }
        return null;
    }

//    /**
//     * 拨打任务批量暂停
//     */
//    public void batchPlanPause() {
//
//    }

    /**
     * 拨打任务批量停止
     *
     * @param batchName
     */
    public void batchPlanStop(String batchName) {
        String url = this.getOutboundConfig().getApiUrl() + "/batchPlanStop";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        requestMap.put("batchName", batchName);//批次名称，用户下唯一
        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,batchPlanStop请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,batchPlanStop处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,batchPlanStop处理失败");
        }
    }

//    /**
//     * 拨打任务批量恢复
//     */
//    public void batchPlanRestart() {
//
//    }

    /**
     * 通过批次号查询该批次的拨打情况
     * 即该批次的统计数据
     *
     * @param batchName
     */
    public void getBatchPlanCallSummary(String batchName) {
        String url = this.getOutboundConfig().getApiUrl() + "/getBatchPlanCallSummary";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        requestMap.put("batchName", batchName);//批次名称，用户下唯一
        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,getBatchPlanCallSummary请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                System.out.println("getBatchPlanCallSummary," + body);
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,getBatchPlanCallSummary处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,getBatchPlanCallSummary处理失败");
        }
    }

    /**
     * 通过批次号查询该批次的通话列表
     * 即该批次的明细及单条状态数据
     */
    public void getBatchPlanList(String batchName) {
        String url = this.getOutboundConfig().getApiUrl() + "/getBatchPlanList";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        requestMap.put("batchName", batchName);//批次名称，用户下唯一
        requestMap.put("page", 1);
        requestMap.put("pageNum", 5000);
        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,getBatchPlanList请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                System.out.println("getBatchPlanList," + body);
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,getBatchPlanList处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,getBatchPlanList处理失败");
        }
    }

    /**
     * 通过批次号查询该批次的通话列表
     * 即该批次的明细及单条状态数据
     */
    public void getBatchPlanCallList(String batchName, int currentPage, int pageNum) {
        String url = this.getOutboundConfig().getApiUrl() + "/getBatchPlanCallList";
        TreeMap<String, Object> requestMap = new TreeMap<>();
        requestMap.put("batchName", batchName);//批次名称，用户下唯一
        requestMap.put("page", currentPage);//页码
        requestMap.put("pageNum", pageNum);//每页多少条
        requestMap.put("notifyUrl", getBetterUrl(configUtil == null ? "https://fat-app-api.cashmama.in/" : configUtil.getAdminUrl()) + "/collection/outbound/query/callback");
        String request = addPublicRequestAndSign(requestMap);
        String response = HttpUtil.postPageBodyTimeout(url, headers, request);
        LOGGER.info("外呼系统,getBatchPlanCallList请求及应答,request:{},response:{}", request, response);
        String body = null;
        try {
            JSONObject resp = JSON.parseObject(response);
            if (resp.getInteger("code") == 0 && Boolean.TRUE.equals(resp.getBoolean("success"))) {
                body = resp.getString("body");
                System.out.println("getBatchPlanCallList," + body);
            }
        } catch (Exception e) {
            LOGGER.error("外呼系统,getBatchPlanCallList处理失败,request:{},response:{}", request, response, e);
            throw new ApplicationException("外呼系统,getBatchPlanCallList处理失败");
        }
    }

    private static String getBetterUrl(String url) {
        if (url.endsWith("/")) {
            return url.substring(0, url.length() - 1);
        }
        return url;
    }

    private static class OutboundConfig {
        private String apiUrl;
        private String clientId;
        private String clientSecret;
        private String botenceId;
        private String lineIds;

        public String getApiUrl() {
            return apiUrl;
        }

        public OutboundConfig setApiUrl(String apiUrl) {
            this.apiUrl = apiUrl;
            return this;
        }

        public String getClientId() {
            return clientId;
        }

        public OutboundConfig setClientId(String clientId) {
            this.clientId = clientId;
            return this;
        }

        public String getClientSecret() {
            return clientSecret;
        }

        public OutboundConfig setClientSecret(String clientSecret) {
            this.clientSecret = clientSecret;
            return this;
        }

        public String getBotenceId() {
            return botenceId;
        }

        public OutboundConfig setBotenceId(String botenceId) {
            this.botenceId = botenceId;
            return this;
        }

        public String getLineIds() {
            return lineIds;
        }

        public OutboundConfig setLineIds(String lineIds) {
            this.lineIds = lineIds;
            return this;
        }
    }
}
